﻿using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Text;

namespace Link_eLab.JwtAuthorizePolicy.Extension
{
    /// <summary>
    /// Ocelot下JwtBearer扩展
    /// </summary>
    public static class OcelotJwtBearerExtension
    {
        #region 注入Ocelot下JwtBearer，在ocelot网关的Startup的ConfigureServices中调用

        /// <summary>
        /// 注入Ocelot下JwtBearer，在ocelot网关的Startup的ConfigureServices中调用
        /// </summary>
        /// <param name="services">IServiceCollection</param>
        /// <param name="issuer">发行人</param>
        /// <param name="audience">订阅人</param>
        /// <param name="secret">密钥</param>
        /// <param name="defaultScheme">默认架构</param>
        /// <param name="isHttps">是否https</param>
        /// <returns>JSON结果集</returns>
        public static AuthenticationBuilder AddOcelotJwtBearer(this IServiceCollection services,
            string issuer, string audience, string secret, string defaultScheme, bool isHttps = false)
        {
            var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,
                ValidateIssuer = true,
                ValidIssuer = issuer,           // 发行人
                ValidateAudience = true,
                ValidAudience = audience,       // 订阅人
                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero,
                RequireExpirationTime = true,
            };
            return services.AddAuthentication(options =>
            {
                options.DefaultScheme = defaultScheme;
            })
            .AddJwtBearer(defaultScheme, opt =>
            {
                // 不使用https
                opt.RequireHttpsMetadata = isHttps;
                opt.TokenValidationParameters = tokenValidationParameters;
            });
        }

        #endregion

        #region 注入Ocelot Jwt策略，在业务API应用中的Startup的ConfigureServices调用

        /// <summary>
        /// 注入Ocelot Jwt策略，在业务API应用中的Startup的ConfigureServices调用
        /// </summary>
        /// <param name="services">IServiceCollection</param>
        /// <param name="issuer">发行人</param>
        /// <param name="audience">订阅人</param>
        /// <param name="secret">密钥</param>
        /// <param name="defaultScheme">默认架构</param>
        /// <param name="policyName">自定义策略名称</param> 
        /// <param name="openJwt">是否开启jwt验证</param>
        /// <param name="isHttps">是否https</param>
        /// <returns>JSON结果集</returns>
        public static AuthenticationBuilder AddOcelotPolicyJwtBearer(this IServiceCollection services,
            string issuer, string audience, string secret, string defaultScheme, string policyName, string openJwt, bool isHttps = false)
        {
            var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));

            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,
                ValidateIssuer = true,
                ValidIssuer = issuer,           // 发行人
                ValidateAudience = true,
                ValidAudience = audience,       // 订阅人
                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero,
                RequireExpirationTime = true,
            };
            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
            var permissionRequirement = new PermissionRequirement(
                issuer,
                audience,
                signingCredentials,
                openJwt);

            // 注入授权Handler
            services.AddSingleton(permissionRequirement);
            services.AddSingleton<IAuthorizationHandler, PermissionHandler>();

            return services.AddAuthorization(options =>
            {
                options.AddPolicy(policyName, policy => policy.Requirements.Add(permissionRequirement));
            })
            .AddAuthentication(options =>
            {
                options.DefaultScheme = defaultScheme;
            })
            .AddJwtBearer(defaultScheme, o =>
            {
                // 不使用https
                o.RequireHttpsMetadata = isHttps;
                o.TokenValidationParameters = tokenValidationParameters;
            });
        }

        #endregion

        #region 注入Token生成器参数，在token生成项目的Startup的ConfigureServices中使用

        /// <summary>
        /// 注入Token生成器参数，在token生成项目的Startup的ConfigureServices中使用
        /// </summary>
        /// <param name="services">IServiceCollection</param>
        /// <param name="issuer">发行人</param>
        /// <param name="audience">订阅人</param>
        /// <param name="secret">密钥</param> 
        /// <returns>JSON结果集</returns>
        public static IServiceCollection AddJTokenBuild(this IServiceCollection services, string issuer, string audience, string secret)
        {
            var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

            var permissionRequirement = new PermissionRequirement(
                issuer,
                audience,
                signingCredentials,
                "True");
            return services.AddSingleton(permissionRequirement);
        }

        #endregion

    }
}